home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------------
- #
- # TV-Man.Sound.c
- #
- # Copyright © Apple Computer, Inc. 1989-1990
- # All rights reserved.
- #
- #
- # All the pertinent code which provides both the control of the beep style as
- # well as the generation of the beep itself is found in this file.
- #
- # In order to have an evironment which predictable events happen several definitions
- # must be established. The most critical is in the file architecture. Each functional
- # block will have its own source and header file. The main project file, in this
- # case TV-Man, will have its header file included with all other files. This will
- # allow for global constants. The utility source file shall contain functions that
- # are general purpose in nature and that can be used by all other functions. These
- # are intended not to be application or major block specific. In order for this to be
- # accomodated all functions in the utility source file must use only the information
- # that is passed to them or information that can be gleaned from the system via
- # toolbox calls. There will be no header file associated with the utility file as this
- # will destroy the intent of the utilities.
- #
- # There are several files which contain information which is global in nature .These
- # file are included in the main project header file. They are: x.Errors.h, x.Ext.h,
- # x.Protos.h, x.Menus.h. The reason for containing them in seperate files is one of
- # convienience and accesability.
- #
- #
- # Revision Log:
- #
- # 8-21-91 RGK Creation
- #
- #
- ------------------------------------------------------------------------------*/
-
-
- /* This is a list of all local includes necessary for this program. */
-
- #include "TV-Man.h"
- #include "TV-Man.Sound.h"
-
-
-
-
- /*-------------------------------------------------------------------------------*/
- /* These are the globals used in the making of sounds and the sound dialog box */
-
- BeepChan gSopranoChan; /* beep channel 1 (not sound a channel) */
- BeepChan gAltoChan; /* beep channel 2 */
- BeepChan gTenorChan; /* beep channel 3 */
- BeepChan gBassChan; /* beep channel 4 */
- BeepChan gTestChan; /* beep channel for the test beep */
-
- Beep gBeepData; /* global beep variables used by the dialog box */
- Beep gBeepDataT; /* global beep variables for test beep */
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /*----------------------------------------------------------------------------------*/
- /* This first section is the interface calls between BeepMaster.lib library and the
- outside world. All the interface calls are in pascal for use with the CPU
- Diagnostics Sequencer. */
-
-
- /*----------------------------------------------------------------------------------*/
- /* This will return the version number of the sound stuff. This is only
- used as part of the BeepMgr.lib which is useable in other programs */
-
- pascal long SoundVersion()
- {
- return(SndVerNumber);
- }/* SoundVersion */
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This will initalize all the necessary globals for the Sound Stuff. */
-
- pascal void SoundInit()
- {
- InitChannel(&gSopranoChan, rSopranoBData);
- InitChannel(&gAltoChan, rAltoBData);
- InitChannel(&gTenorChan, rTenorBData);
- InitChannel(&gBassChan, rBassBData);
- InitChannel(&gTestChan, rTestBData);
- }/* SoundInit */
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function will set all the beep enable flags. The call to "SoundCheck"
- will start the Noise making. */
- pascal void SoundEnable( void )
- {
- SetAllSounds();
- }/* SoundEnable */
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function is designed to be called by the event loop. It is used to continue
- a beep after the interrupt has identified that the sound queue has been emptied.
- A beep channel is identified and the rest of the beep control processing is
- called. However, before processing a beep channel the error flag is checked for
- any previous errors, if so that beep channel is bypassed. */
-
- pascal void SoundCheck(void)
- {
- if(gSopranoChan.Error == false) ProcessBeep(&gSopranoChan);
- if(gAltoChan.Error == false) ProcessBeep(&gAltoChan);
- if(gTenorChan.Error == false) ProcessBeep(&gTenorChan);
- if(gBassChan.Error == false) ProcessBeep(&gBassChan);
- }/* SoundCheck */
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function will dispose of the sound channel which will stop the beeping
- immedatly. */
- pascal void SoundStop(void)
- {
- KillSoundChannels();
- }/* SoundStop */
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function will first clear all the beep enable flags and then dispose of the
- sound channel which will stop the beeping immedatly. */
- pascal void SoundDisable(void)
- {
- ClearAllSounds();
- KillSoundChannels();
- }/* SoundDisable */
-
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* set up the Sound dialog box */
-
- pascal void SopranoControls()
- {
- DoSoundControls(rSopranoBData);
- }
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* set up the Sound dialog box */
-
- pascal void AltoControls()
- {
- DoSoundControls(rAltoBData);
- }
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* set up the Sound dialog box */
-
- pascal void TenorControls()
- {
- DoSoundControls(rTenorBData);
- }
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* set up the Sound dialog box */
-
- pascal void BassControls()
- {
- DoSoundControls(rBassBData);
- }
-
-
-
- /*----------> the end of the library interface <---------------------*/
-
- /*----------------------------------------------------------------------------------*/
- /* set up the Sound dialog box */
-
- void DoSoundControls(rsrc)
- short rsrc;
- {
- short itemhit;
- DialogPtr dialog;
- MenuHandle menu;
- BeepHdl beephdl;
-
-
- KillSoundChannels();
-
- dialog = GetNewDialog(rSounds,nil,(WindowPtr)-1);
- if((dialog == nil) || (ResError() != noErr))
- {
- Error(eMinor, eMinorDialog);
- return;
- }
-
- /* the following resource grab is not used here but is used by the functions which
- follow. By getting the menu resource and checking it now we are in a better
- position to recover from an error caused by not capturing the resource */
-
- menu = GetMenu(rBeepMenu);
- if((menu == nil) || (ResError() != noErr))
- {
- Error(eMinor, eMinorMenu);
- return;
- }
-
- /* Set up the Beep data globals */
- beephdl = (BeepHdl)GetResource('beep', rsrc);
- if((beephdl == nil) || (ResError() != noErr))
- {
- Error(eMinor, eMinorRsrc);
- return;
- }
-
- HNoPurge((Handle)beephdl); /* don't allow the resource to be purged */
- InitTheValues(dialog, beephdl); /* set up all the values */
- ShowWindow(dialog);
-
-
- /* Now we will use the standard Modal dialog process to handle the user. The sound filter
- function will handle all the special cases during this process. The 2 choices upon
- returning are the cancel and done. If cancel leave without changing resource */
-
- while(itemhit != BeepCancelId)
- {
- ModalDialog((ModalFilterProcPtr)SoundFilter, &itemhit);
- if(itemhit == BeepDoneId)
- {
- FullRangeCheck(dialog);
- SaveTheValues( dialog, beephdl, true);
- break;
- }
- }
- HPurge((Handle)beephdl); /* allow purgeing again */
- DisposeMenu(menu);
- DisposeDialog(dialog);
-
- /* gSopranoChan.Error = false; set the sound error to false to signify that a
- new sound setup is avaliable */
- }/* DoSound */
-
-
-
-
-
-
- /*---------------------------------------------------------------------------------------*/
- /* This function is used to draw the ring around the done button. */
-
- pascal void DrawBeepDone(dialog, item)
- DialogPtr dialog;
- short item;
- {
- short itemtype;
- Rect itemrect;
- Handle itemhdl;
- PenState savepen;
-
- GetPenState(&savepen);
- GetDItem(dialog, item, &itemtype, &itemhdl, &itemrect);
- PenSize(3, 3);
- FrameRoundRect(&itemrect, 16, 16);
- SetPenState(&savepen);
- }/* DrawBeepDone */
-
-
-
-
-
-
-
-
- /*---------------------------------------------------------------------------------------
- This function is used to draw useritems in dialog boxes. The item number as well as
- handle to the dialog box is needed. */
-
- pascal void DrawBeepType(dialog, item)
- DialogPtr dialog;
- short item;
- {
- short itemtype;
- Rect itemrect;
- Handle itemhdl;
- Str255 menutext;
-
- GetDItem(dialog, item, &itemtype, &itemhdl, &itemrect);
- InsetRect(&itemrect, -1, -1);
- GetItem(GetMenu(rBeepMenu), gBeepData.Type, menutext);
-
- /* make the box and shadow it */
- FrameRect(&itemrect);
- MoveTo(itemrect.right, itemrect.top + 2);
- LineTo(itemrect.right, itemrect.bottom);
- LineTo(itemrect.left + 2, itemrect.bottom);
-
- /* now add the text */
- MoveTo(itemrect.left + LeftMargin, itemrect.bottom - BottomMargin);
- DrawString(menutext);
- }/* DrawBeepType */
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This is the Sound dialog box filter function. This means all mouse events and
- key strokes are processed by this function as long as the Sound dialog box is
- on the screen */
-
- pascal Boolean SoundFilter(dialog, event, itemhit)
- DialogPtr dialog;
- EventRecord *event;
- short *itemhit;
-
- {
- char key;
- short itemtype, itemid, part;
- long value;
- Rect itemrect;
- Handle itemhdl;
- Point mouseloc;
-
- SetPort(dialog);
- switch(event->what)
- {
- case keyDown:
- case autoKey:
- key = event->message;
- if((key == ENTERKEY) || (key == RETURNKEY))
- {
- GetDItem(dialog, BeepDoneId, &itemtype, &itemhdl, &itemrect);
- HiliteControl((ControlHandle)itemhdl, 1);
- Delay(3, &value);
- *itemhit = BeepDoneId;
- return(true);
- }
- break;
-
- case mouseDown:
- mouseloc = event->where;
- GlobalToLocal(&mouseloc);
- itemid = (FindDItem(dialog, mouseloc)) + 1;
- switch(itemid)
- {
- case BeepEnableId:
- UpDateSlider(dialog, BeepVolumeId);
- UpDateSlider(dialog, BeepFreqId);
- GetDItem(dialog, BeepEnableId, &itemtype, &itemhdl, &itemrect);
- part = TrackControl((ControlHandle)itemhdl, mouseloc, (ProcPtr) -1);
- if(part == inCheckBox) ToggleControl((ControlHandle)itemhdl);
- return(true);
- break;
-
- case BeepTypeId:
- UpDateSlider(dialog, BeepVolumeId);
- UpDateSlider(dialog, BeepFreqId);
- DoBeepTypeMenu(dialog);
- return(true);
- break;
-
- case BeepVolumeCntlId:
- DoSliders(dialog, mouseloc, BeepVolumeCntlId);
- return(true);
- break;
-
- case BeepFreqCntlId:
- DoSliders(dialog, mouseloc, BeepFreqCntlId);
- return(true);
- break;
-
- case BeepDoneId:
- GetDItem(dialog, BeepDoneId, &itemtype, &itemhdl, &itemrect);
- HiliteControl((ControlHandle)itemhdl, true);
- Delay(3, &value);
- *itemhit = BeepDoneId;
- return(true);
- break;
-
- case TestBeepId:
- TestTheBeep(dialog);
- return(true);
- break;
-
- case BeepCancelId:
- GetDItem(dialog, BeepCancelId, &itemtype, &itemhdl, &itemrect);
- HiliteControl((ControlHandle)itemhdl, true);
- Delay(3, &value);
- *itemhit = BeepCancelId;
- return(true);
- break;
- }
- FullRangeCheck(dialog);
- break;
- }
- return(false);
- }/* SoundFilter */
-
-
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* Lets set up all the values in the dialog boxes and all the other information needed
- by the sound dialog box from the appointed resource. */
-
- void InitTheValues(dialog, beephdl)
- DialogPtr dialog;
- BeepHdl beephdl;
- {
- short itemtype;
- Rect itemrect;
- Handle itemhdl;
-
- /* Initalize the necessary globals */
- gBeepData.Type = ((*beephdl)->Type) - (rBeepMenu * 10);
-
- /* make all the pertinent text boxes in the dialog reflect the actual values from
- the beep resource */
- Short2Text((*beephdl)->Length, dialog, BeepLengthId);
- Short2Text((*beephdl)->QTime, dialog, BeepQTimeId);
- Short2Text((*beephdl)->Count, dialog, BeepCountId);
- Short2Text((*beephdl)->Delay, dialog, BeepDelayId);
- Short2Text((*beephdl)->Volume, dialog, BeepVolumeId);
- Short2Text((*beephdl)->Freq, dialog, BeepFreqId);
-
- /* Set the Controls to the correct values. */
- GetDItem(dialog, BeepEnableId, &itemtype, &itemhdl, &itemrect);
- SetCtlValue((ControlHandle)itemhdl, (Boolean)((*beephdl)->Enabled));
- GetDItem(dialog, BeepVolumeCntlId, &itemtype, &itemhdl, &itemrect);
- SetCtlValue((ControlHandle)itemhdl, ((*beephdl)->Volume) * -1);
- GetDItem(dialog, BeepFreqCntlId, &itemtype, &itemhdl, &itemrect);
- SetCtlValue((ControlHandle)itemhdl, ((*beephdl)->Freq) * -1);
-
- /* now set the beep type pop up menu */
- GetDItem(dialog, BeepTypeId, &itemtype, &itemhdl, &itemrect);
- SetDItem(dialog, BeepTypeId, itemtype, (Handle)DrawBeepType, &itemrect);
-
- /* set the done button to indicate a default button */
- GetDItem(dialog, BeepDoneId, &itemtype, &itemhdl, &itemrect);
- InsetRect(&itemrect, -4, -4);
- SetDItem(dialog, DoneRingId, userItem, (Handle)DrawBeepDone, &itemrect);
-
- /* now depending on the resource data assigned the title will be changed */
- GetDItem(dialog, BeepTitleId, &itemtype, &itemhdl, &itemrect);
- SetIText(itemhdl, (*beephdl)->Title);
- }/* InitTheValues */
-
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* Lets save all the values in the dialog boxes and place them into the appointed
- resource. If the "doit" flag is false the resource will not be updated otherwise
- it will. */
-
- void SaveTheValues(dialog, beephdl, doit)
- DialogPtr dialog;
- BeepHdl beephdl;
- Boolean doit;
- {
- short itemtype;
- Rect itemrect;
- Handle itemhdl;
-
- /* put all the new values into the Beep recource data */
- GetDItem(dialog, BeepEnableId, &itemtype, &itemhdl, &itemrect);
- (*beephdl)->Enabled = GetCtlValue((ControlHandle)itemhdl);
- (*beephdl)->Type = gBeepData.Type + (rBeepMenu * 10);
- (*beephdl)->Length = Text2Short(dialog, BeepLengthId);
- (*beephdl)->QTime = Text2Short(dialog, BeepQTimeId);
- (*beephdl)->Count = Text2Short(dialog, BeepCountId);
- (*beephdl)->Delay = Text2Short(dialog, BeepDelayId);
- (*beephdl)->Volume = Text2Short(dialog, BeepVolumeId);
- (*beephdl)->Freq = Text2Short(dialog, BeepFreqId);
-
- if(doit == true)
- {
- /* Now lets change the Beep resource */
- ChangedResource((Handle)beephdl); /* mark it changed */
- WriteResource((Handle)beephdl); /* make the change permanent */
- }
- }/* SaveTheValues */
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function puts up the Beep Type menu. As long as the user whishes to interact
- with the Beep Type menu program control will stay in this function. The
- 'PopUpMenuSelect' function will capture control and handle the highlighting and
- selection of the menu items. */
-
- void DoBeepTypeMenu(dialog)
- DialogPtr dialog;
- {
- short itemtype, olditem;
- Rect itemrect, box;
- Handle itemhdl;
- MenuHandle menu;
- long value;
-
- GetDItem(dialog, BeepTypeId, &itemtype, &itemhdl, &itemrect);
-
- /* we are now going to get a resource, normally a safty measure would entail checking
- for errors after the GetResource call. However, early in this whole dialog process
- I got and checked this resource in a place where it was more appropreate to handle
- the error. */
- menu = GetMenu(rBeepMenu);
-
- InsertMenu(menu, -1);
- CalcMenuSize(menu); /* for a Menu Mgr Bug */
- olditem = gBeepData.Type; /* save the old type */
- CheckItem(menu, gBeepData.Type, true); /* and check it */
-
- /* globalize the menu box and aquire the new selection */
- box = itemrect;
- LocalToGlobal(&TopLeft(box));
- value = PopUpMenuSelect(menu, box.top, box.left, gBeepData.Type);
- gBeepData.Type = LoWord(value);
-
- /* now lets uncheck the old type, check the new type and erase the old selection
- and put in the new one (for the current dialog box view) */
- CheckItem(menu, olditem, false);
- CheckItem(menu, gBeepData.Type, true);
- EraseRect(&itemrect);
- DrawBeepType(dialog, BeepTypeId);
- DeleteMenu(rBeepMenu);
- }/* DoBeepTypeMenu */
-
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function is called to force all the controls an edit boxes to be matched to
- their correct limits. The process of the functions that this function calls will
- check the values and if the limits are exceeded change the values to the closest
- limit */
-
- void FullRangeCheck(dialog)
- DialogPtr dialog;
- {
- UpDateSlider(dialog, BeepVolumeId);
- UpDateSlider(dialog, BeepFreqId);
- RangeCheckShort(dialog, BeepLengthId, LengthMin, LengthMax);
- RangeCheckShort(dialog, BeepQTimeId, QTimeMin, QTimeMax);
- RangeCheckShort(dialog, BeepCountId, CountMin, CountMax);
- RangeCheckShort(dialog, BeepDelayId, DelayMin, DelayMax);
- }/* FullRangeCheck */
-
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function is called when a mouse event has been found in a scroll bar. The
- display area of the slider control is by definition the next item id. This structure
- allows this generic type of function to keep the corrisponding edit box current
- with the value of the slider. Also remember the value contained in the controls
- are negative requiring the sign adjustment by the "* -1". */
-
- void DoSliders(dialog, mouseloc, itemid)
- DialogPtr dialog;
- Point mouseloc;
- short itemid;
- {
- short value;
- ControlHandle control;
-
- if(FindControl(mouseloc, dialog, &control) == inThumb)
- {
- value = TrackControl(control, mouseloc, (ProcPtr)-1);
- }
- else
- {
- value = TrackControl(control, mouseloc, (ProcPtr)SoundScroll);
- }
- value = GetCtlValue(control) * (-1);
- Short2Text(value, dialog, itemid + 1);
- }/* DoSliders */
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function updates the slider controls based on the corrisponding edit box.
- The item Id passed must be the Id of the text box. This function will determine
- the appropreate control to adjust. Also if the value in the edit box is over the
- limit of the control the edit box will be modified to reflect the limit and the
- control will be updated accordingly. */
-
- void UpDateSlider(dialog, itemid)
- DialogPtr dialog;
- short itemid;
- {
- short itemtype, textvalue, value;
- Rect itemrect;
- Handle itemhdl;
-
- GetDItem(dialog, itemid, &itemtype, &itemhdl, &itemrect);
- textvalue = Text2Short(dialog, itemid) * (-1);
- GetDItem(dialog, itemid - 1, &itemtype, &itemhdl, &itemrect);
- value = CheckControlRange(textvalue, (ControlHandle)itemhdl);
- if(value == textvalue)
- {
- SetCtlValue((ControlHandle)itemhdl, value);
- return;
- }
- else
- {
- SetCtlValue((ControlHandle)itemhdl, value);
- Short2Text(value * (-1), dialog, itemid);
- return;
- }
- }/* UpDateSlider */
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function is called when a mouse event has been found in a scroll bar. remember
- the control values are all negative to allow for the fact the screen has "zero" as
- the top. this allows larger absoute number to go up. However, all the calculations
- and comparisons need to be "backwards". */
-
- pascal void SoundScroll(control, part)
- ControlHandle control;
- short part;
- {
- short value;
-
- switch(part)
- {
- case inUpButton:
- value = GetCtlValue(control) - 1;
- if(value < GetCtlMin(control))
- {
- value = GetCtlMin(control);
- }
- SetCtlValue(control, value);
- break;
-
- case inDownButton:
- value = GetCtlValue(control) + 1;
- if(value > GetCtlMax(control))
- {
- value = GetCtlMax(control);
- }
- SetCtlValue(control, value);
- break;
-
- case inPageUp:
- value = GetCtlValue(control) - JumpAmount(control, JumpCount);
- if(value < GetCtlMin(control))
- {
- value = GetCtlMin(control);
- }
- SetCtlValue(control, value);
- break;
-
- case inPageDown:
- value = GetCtlValue(control) + JumpAmount(control, JumpCount);
- if(value > GetCtlMax(control))
- {
- value = GetCtlMax(control);
- }
- SetCtlValue(control, value);
- break;
- }
- }/* SoundScroll */
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function is used by the dialog box to test the currently described beep.
- This will not change the resource used by the actual program but uses a test
- beep resource. This function will also lock into a loop that will test for key
- inputs.If any key is pressed during the test beep the sound will stop and the
- sound channel disposed of. This is not a recomended procedure because any Apple
- Events (or any others) will not be processed. */
-
- void TestTheBeep(dialog)
- DialogPtr dialog;
- {
- BeepHdl beephdl;
- SndChannelPtr channel;
- EventRecord event;
- short itemtype;
- Rect itemrect;
- Handle itemhdl;
-
-
- /* Highlight the Test button while it is being pushed */
- GetDItem(dialog, TestBeepId, &itemtype, &itemhdl, &itemrect);
- HiliteControl((ControlHandle)itemhdl, true);
-
- GetNextEvent(mUpMask, &event);
- while(event.what != mouseUp)
- {
- GetNextEvent(mUpMask, &event);
- }
- HiliteControl((ControlHandle)itemhdl, false);
-
- /* set up the test beep resource */
- beephdl = (BeepHdl)GetResource('beep', rTestBData);
- if((beephdl == nil) || (ResError() != noErr))
- {
- Error(eMinor, eMinorRsrc);
- return;
- }
- FullRangeCheck(dialog);
- SaveTheValues(dialog, beephdl, false);
- channel = DoSound(beephdl);
-
- /* now send a helpful message */
- GetDItem(dialog, BeepMessageId, &itemtype, &itemhdl, &itemrect);
- SetIText(itemhdl, "\p)) Any key will kill Beeps.");
-
- if(channel != nil)
- {
- gTestChan.InProcess = true;
- while(gTestChan.InProcess)
- {
- GetNextEvent(keyDownMask, &event);
- if(event.what == keyDown) break;
- }
- if(SndDisposeChannel(channel, true) != noErr)
- {
- Error(eMajor, eMajorNoDispose);
- }
- }
-
- /* now delete the helpful message */
- GetDItem(dialog, BeepMessageId, &itemtype, &itemhdl, &itemrect);
- SetIText(itemhdl, "\p");
- }/* TestTheBeep */
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function checks the sound process for the identifed beep. It processes all the
- various bits of information to determine whether or not to clear the sound
- channel, get another sound setup or ignore everything. Each beep is
- handled seperatly. */
-
- void ProcessBeep(beepchan)
- BeepCPtr beepchan;
- {
- BeepHdl beephdl;
- SndChannelPtr channel;
-
- if(beepchan->InProcess == false)
- {
- if(beepchan->SndChannel == nil)
- {
- beephdl = (BeepHdl)GetResource('beep', beepchan->RsrcId);
- if((beephdl == nil) || (ResError() != noErr))
- {
- Error(eMinor, eMinorRsrc);
- beepchan->Error = true;
- return;
- }
- if((*beephdl)->Enabled == 1)
- {
- channel = DoSound(beephdl);
- if(channel == nil) /* check for the error */
- {
- beepchan->InProcess = false;
- beepchan->SndChannel = nil;
- beepchan->Error = true;
- }
- else
- {
- beepchan->InProcess = true;
- beepchan->SndChannel = channel;
- }
- }
- }
- else
- {
- KillBeepChannel(beepchan);
- }
- }
- }/* ProcessBeep */
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function is used to set up a sound and play it. All data pertinent to the
- sound will be found in the Beep data resource pointed to by the passed handle.
- This will allow this function to to use the latest data for the Beep. */
-
- SndChannelPtr DoSound(beephdl)
- BeepHdl beephdl;
- {
- Handle sndhdl;
- OSErr error;
- SndChannelPtr channel;
-
- /* Load the 'snd' resource based on the Beep Type found in the Beep resource */
- sndhdl = GetResource('snd ', (*beephdl)->Type); /* rem the space in 'snd ' */
- if((sndhdl == nil) || (ResError() != noErr))
- {
- Error(eMinor, eMinorNoSnd);
- return(nil);
- }
-
- /* Initalize the sound channel */
- channel = (SndChannelPtr)nil;
- error = SndNewChannel(&channel, waveTableSynth, (*beephdl)->Init, SoundIsDone);
- if(error != noErr)
- {
- Error(eMinor, eMinorSound);
- return(nil);
- }
-
- /* play the sound */
- error = SndPlay(channel, sndhdl, true);
- if(error != noErr)
- {
- Error(eMinor, eMinorSPlay);
- return(nil);
- }
- SetUpBeep(beephdl, channel);
- return(channel);
- }/* DoSound */
-
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function will use the initalized the sound channel, and set up the commands
- as specified by the beep data resource. */
-
- void SetUpBeep(beephdl, channel)
- BeepHdl beephdl;
- SndChannelPtr channel;
- {
- SndCommand command;
- short count;
-
- /* set the desired volume */
- command.cmd = ampCmd;
- command.param1 = ((*beephdl)->Volume);
- command.param2 = 0;
- SndDoCommand(channel, &command, false);
-
- for (count = 0; count < ((*beephdl)->Count); count++)
- {
- /* set the length of the beep and the dersired frequency */
- command.cmd = freqDurationCmd;
- command.param1 = ((*beephdl)->Length) * 2;
- command.param2 = ((*beephdl)->Freq);
- SndDoCommand(channel, &command, false);
-
- /* stop the sound */
- command.cmd = quietCmd;
- command.param1 = 0;
- command.param2 = 0;
- SndDoCommand(channel, &command, false);
-
- /* set the length of quite time */
- command.cmd = restCmd;
- command.param1 = ((*beephdl)->QTime) * 2;
- command.param2 = 0;
- SndDoCommand(channel, &command, false);
- }
-
- /* set the length of delay between the beep cycles */
- command.cmd = restCmd;
- command.param1 = ((*beephdl)->Delay) * 2;
- command.param2 = 0;
- SndDoCommand(channel, &command, false);
-
- /* set the callback procedure values. The SoundDone function will be called
- when this point of the queue is reached. See the SoundDone description
- for the proccessing of the SoundChannel */
-
- command.cmd = callBackCmd;
- command.param1 = (*beephdl)->RsrcId;
- command.param2 = SetCurrentA5();
- SndDoCommand(channel, &command, false);
-
- }/* SetUpBeep */
-
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function is used to signify the end of the sound. It will set to false the
- "gInProcess" flag. Since this is an interrupt class of routine no efforts to
- move memory shall be made. This would be disasterous. The flag will be monitored
- in the main event loop. When a transition to false is detected the sound channel
- will be disposed of. When the interrupt command is put into the sound queue the
- resource id of that beep channel is places in as well. When we arrive here the
- we check for a match of the passed resource id and change only the one flag. */
-
- pascal void SoundIsDone(channel, command)
- SndChannelPtr channel;
- SndCommand command;
- {
- long oldA5;
- short id;
-
- id = command.param1; /* get the passed resource Id */
- oldA5 = SetA5(command.param2); /* save the current A5 while setting A5 that was
- passed in the command block. */
- if(gSopranoChan.RsrcId == id) gSopranoChan.InProcess = false;
- if(gAltoChan.RsrcId == id) gAltoChan.InProcess = false;
- if(gTenorChan.RsrcId == id) gTenorChan.InProcess = false;
- if(gBassChan.RsrcId == id) gBassChan.InProcess = false;
- if(gTestChan.RsrcId == id) gTestChan.InProcess = false;
- oldA5 = SetA5(oldA5); /* now restore the origional A5 */
- }/* SoundIsDone */
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function sets all the Beep Enable Flags. */
-
- void SetAllSounds()
- {
- ForceBeepEnable(&gSopranoChan, true);
- ForceBeepEnable(&gAltoChan, true);
- ForceBeepEnable(&gTenorChan, true);
- ForceBeepEnable(&gBassChan, true);
- }/* SetAllSounds */
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function Clears all the Beep Enable Flags. */
-
- void ClearAllSounds()
- {
- ForceBeepEnable(&gSopranoChan, false);
- ForceBeepEnable(&gAltoChan, false);
- ForceBeepEnable(&gTenorChan, false);
- ForceBeepEnable(&gBassChan, false);
- }/* ClearAllSounds */
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function disposes of all the beep channels. This will stop all sounds
- currently in process. */
-
- void KillSoundChannels()
- {
- KillBeepChannel(&gSopranoChan);
- KillBeepChannel(&gAltoChan);
- KillBeepChannel(&gTenorChan);
- KillBeepChannel(&gBassChan);
- }/* KillAllSounds */
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function disposes of the sound channel whose pointer is passed. Since this
- not alter the Beep Enable flags in the resources this is usd as only a temporary
- stoping of the beeps. The next call to "CheckForSound" will restart the beep.*/
-
- void KillBeepChannel(beepchan)
- BeepCPtr beepchan;
- {
- OSErr error = 0;
-
- if(beepchan->SndChannel != nil)
- {
- error = SndDisposeChannel(beepchan->SndChannel, true);
- if(error != noErr)
- {
- beepchan->Error = true; /* kill this channel */
- Error(eMajor, eMajorNoDispose); /* signal the error */
- }
- }
- beepchan->InProcess = false; /* always leave with no beep */
- beepchan->SndChannel = nil; /* and no sound channel */
- }/* KillBeepChannel */
-
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This function forecs the Beep enable Flag to be the specified value in the
- identified Beep resource. */
-
- void ForceBeepEnable(beepchan, value)
- BeepCPtr beepchan;
- Boolean value;
- {
- BeepHdl beephdl;
-
- beephdl = (BeepHdl)GetResource('beep', beepchan->RsrcId);
- if((beephdl == nil) || (ResError() != noErr))
- {
- beepchan->Error = true; /* kill this channel */
- }
- else
- {
- (*beephdl)->Enabled = value; /* Clear the Beep Enable */
- ChangedResource((Handle)beephdl); /* mark it changed */
- WriteResource((Handle)beephdl); /* make the change permanent */
- }
- }/* ForceBeepEnable */
-
-
-
-
-
- /*----------------------------------------------------------------------------------*/
- /* This will initalize all the necessary variables a Beep Channel. It is Important
- to note that the beep.Error will only be set to false once, here. If at any
- time during the course of this application the beep channel with this error set
- will be ignored. Any use of a resource or sound channel associated with this
- beep channel will set the Error flag.*/
-
- void InitChannel(beepchan, rsrc)
- BeepCPtr beepchan;
- short rsrc;
- {
- beepchan->RsrcId = rsrc; /* id the recource to the beep channel */
- beepchan->Error = false; /* there can be no error yet */
- beepchan->InProcess = false; /* and no beep */
- beepchan->SndChannel = nil; /* and no sound channel */
- }/* InitChannel */